using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using JetBrains.Annotations;
using Kaleida.ServiceMonitor.Framework;

namespace Kaleida.ServiceMonitor.Model.Runtime
{
    public class CompiledScript
    {
        public static readonly Duration DefaultPollInterval = new Duration(1000, "ms");

    	private readonly Guid id;
    	private readonly string name;
    	private readonly CompiledNode root;

		public CompiledScript([NotNull] string name) : this(name, new CompiledNode(new CompiledScriptModule(name)))
		{
		}

		public CompiledScript([NotNull] string name, [NotNull] CompiledNode rootNode)
		{
			if (name == null) throw new ArgumentNullException("name");
			if (rootNode == null) throw new ArgumentNullException("rootNode");
			this.name = name;
		    id = Guid.NewGuid();
			root = rootNode;
		}

        public Guid Id
        {
            get { return id; }
        }

        public string Name
    	{
    		get { return name; }
    	}

    	[NotNull]
        public CompiledNode Root
        {
            get { return root; }
        }

        public string BuildSummary()
        {
            var summary = new StringBuilder();
            
            var allScriptModules = AllScriptModules;
            
            if (allScriptModules.Count() > 1)
            {
                summary.AppendFormat("Script contains {0} nested modules:\r\n\r\n", allScriptModules.Count());
            }

            summary.Append(BuildSummary(root));

            return summary.ToString();
        }

        private static string BuildSummary(CompiledNode node)
        {
            if (node.IsLeaf)
                return node.ScriptModule.BuildSummary();
            
            var summary = new StringBuilder();
            foreach (var child in node.ScriptGroup.Children)
            {
                summary.Append(BuildSummary(child));
            }
            
            return summary.ToString();
        }

        public IList<CompiledScriptModule> AllScriptModules
    	{
			get { return GetAllChildModules(root); }
    	}

    	private static List<CompiledScriptModule> GetAllChildModules(CompiledNode compiledNode)
    	{
    		return compiledNode.IsLeaf
				? new List<CompiledScriptModule>{compiledNode.ScriptModule}
				: compiledNode.ScriptGroup.Children.SelectMany(GetAllChildModules).ToList();
    	}
    }
}